﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Windows.Forms;
using QDasTransfer.Classes;

namespace QDasTransfer.Transducer
{
    public class TransducerBase
    {
        #region 属性
        /// <summary>
        /// System configuration file.
        /// </summary>
        public ParamaterData pd = null;

        /// <summary>
        /// 显示的公司名称，这个用于显示在封面上，如Mairi。
        /// </summary>
        public string CompanyName;

        /// <summary>
        /// 转换器的版本信息，每家公司使用自己的版本号，如果为空则使用转换器的版本号。(不要带V）
        /// </summary>
        public string VertionInfo;

        /// <summary>
        /// 文件日志列表，转换后可读取此列表。
        /// </summary>
        public List<TransLog> LogList = new List<TransLog>();

        /// <summary>
        /// 转换完成的情况。
        /// </summary>
        public double Percentage = 0;

        /// <summary>
        /// 当前正在转换的文件。
        /// </summary>
        public string CurrentInFile;

        /// <summary>
        /// 最后一次输出的DFQ文件。
        /// </summary>
        public string LastOutputDfqFile;

        /// <summary>
        /// 当文件转换完成时发生此事件。
        /// </summary>
        public event TransFileCompleteEventHandler TransFileComplete;
         

        private ConvertTask currentInputPath;

        /// <summary>
        /// 用于专用的Table页属性配置。
        /// </summary>
        public virtual UserControl ConfigPage { get; set; }

        #endregion

        public TransducerBase()
        {
            pd = ParamaterData.Load("config.xml");
            pd.extentions.Clear();
            Initialize();
        }

        #region 可重载函数

        /// <summary>
        ///  Initialize transducer.
        /// </summary> 
        public virtual void Initialize()
        {

        }

        /// <summary>
        /// 转换指定目录下的所有文件。
        /// </summary>
        /// <param name="folder">Input folder that contains input files and sub folders to be processed.</param>
        public virtual void DealFolder(string folder)
        {
            string[] files = Directory.GetFiles(folder);
            foreach (string s in files)
            {
                ProcessFile(s);
                Percentage++;
            }

            if (pd.TraverseSubfolders)
            {
                foreach (string subfolder in Directory.GetDirectories(folder))
                {
                    DealFolder(subfolder);
                }
            }
        }

        public void ProcessInput(ConvertTask ip)
        {
            Thread.Sleep(100);
            LogList.Clear();
            try
            {
                currentInputPath = ip;
                if (ip.InputType == 0)
                    ProcessFile(ip.FullPath);
                else
                    DealFolder(ip.FullPath);
            }
            catch (Exception ex) { Console.WriteLine(ex.Message); }
        }

        /// <summary>
        /// 转换文件函数，一般只需要重写这个函数即可，会被DealFile()调用。
        /// </summary>
        /// <param name="path">需要转换的文件路径。</param>
        /// <returns></returns>
        public virtual bool TransferFile(string path)
        {

            return true;
        }


        public void AddLog(LogType logType, string message, string input, string output = "-", string remark = "-")
        {
            LogList.Add(new TransLog(logType, message, input, output, remark));
        }

        /// <summary>
        /// 处理文件函数，包括处理前后的主要业务逻辑。
        /// </summary>
        /// <param name="infile"></param>
        /// <returns></returns>
        public virtual bool ProcessFile(string infile)
        {
            // 如果文件不存在或后缀名不匹配，就直接忽略，不产生任何记录。
            if (!File.Exists(infile))
            {
                AddLog(LogType.Fail, "输入文件不存在。", infile);
                return false;
            }

            // 如果文件不存在或后缀名不匹配，就直接忽略，不产生任何记录。
            if (pd.extentions.IndexOf(Path.GetExtension(infile).ToLower()) < 0)
            {
                AddLog(LogType.Fail, "输入文件扩展名不正确。", infile);
                return false;
            }

            //当前正在转换的文件。
            CurrentInFile = infile;


            bool success = TransferFile(infile);


            // Processes input file.
            switch (pd.ProcessSourceFileType)
            {
                // move inputfile ==> backup folder. 
                case 0:
                    // select the backup folder according to the processing result.
                    string backupFolder = success ? pd.FolderForSuccessed : pd.FolderForFailed;

                    // create backup directory.
                    Directory.CreateDirectory(backupFolder);
                    if (!Directory.Exists(backupFolder))
                    {
                        AddLog(LogType.Fail, "备份文件夹 '" + backupFolder + "' 创建失败。", infile);
                        break;
                    }

                    string outfile = null;
                    switch (pd.KeepBackupFolderStructType)
                    {
                        case 0:
                            // construct outputfile with a unique file name. 
                            outfile = FileHelper.AddIncreamentId(backupFolder + "\\" + Path.GetFileName(infile));
                            break;
                        case 1:
                            outfile = FileHelper.GetOutFolder(infile,
                               currentInputPath.InputType == 0 ? "" : currentInputPath.FullPath,
                               backupFolder);
                            Directory.CreateDirectory(Path.GetDirectoryName(outfile));
                            break;
                    }

                    // copy file. If failed, add the error to logs.
                    if (!FileHelper.CopyFile(infile, outfile))
                    {
                        AddLog(LogType.Fail, String.Format("复制文件 '{0}' 至 '{1}' 失败。", infile, outfile), infile);
                        break;
                    }

                    // delete source file.
                    if (!FileHelper.DeleteFile(infile))
                    {
                        AddLog(LogType.Fail, String.Format("文件 {0} 删除失败。", infile), infile);
                    }
                    break;

                case 1: // no change.
                    break;

                case 2: // delete files.
                    FileHelper.DeleteFile(infile);
                    break;

                case 3: // customized.
                    break;
            }

            // invoke the TransFileComplete event. Note ? denotes nullable.
            foreach (var log in LogList)
            {
                TransFileComplete.Invoke(this, log);
            }

            return true;
        }

        #endregion


        /// <summary>
        /// 如果名称已经存在，则根据pd的处理原则对重名的文件进行重命名，保证文件名不重复。
        /// </summary>
        /// <param name="filepath">文件名称</param>
        /// <returns></returns>
        public string ProcessOutputFileNameIfRepeated(string filepath)
        {
            // 添加日期时间戳。
            if (string.IsNullOrEmpty(pd.CostomizedDateTimeFormat))
            {

            }
            else if(pd.CostomizedDateTimeFormat == "#default#")
            {
                filepath = filepath.Replace(".dfq", "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".dfq");
            }
            else
            {
                filepath = filepath.Replace(".dfq", "_" + DateTime.Now.ToString(pd.CostomizedDateTimeFormat) + ".dfq");
            }

  

            if (File.Exists(filepath))
            {
                switch (pd.DealSameOutputFileNameType)
                {
                    case 0: // 直接覆盖。
                        FileHelper.DeleteFile(filepath);
                        break;

                    case 1: //添加时间戳
                        filepath = filepath.Replace(".dfq", "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".dfq");
                        break;

                    case 2: //添加自增长编号。
                        filepath = FileHelper.AddIncreamentId(filepath);
                        break;
                    case 3: // 合并两个文件，由转换器自行处理。
                        
                        break;
                }
                Directory.CreateDirectory(Path.GetDirectoryName(filepath));
            }

            return filepath;
        }

        /// <summary>
        /// 如果文件名称中包括非法字符（\/:?\"<>|），则使用指定字符替换（默认为下划线）。
        /// </summary>
        /// <param name="filename">待校验的文件名称。</param>
        /// <param name="replacement">非法字符的替换字符。</param>
        public string VarifyFilename(string filename, string replacement = "_")
        {
            string illegals = "\\/:?\"<>|";
            string newfilename = Path.GetFileName(filename);
            for (int i = 0; i < illegals.Length; i++)
                newfilename = newfilename.Replace(illegals[i], '_');
            return newfilename;
        }
    }
}
